namespace HybridCLR.Extension.Editor
{
    public partial class Commond
    {
        public static void CatalogUpdate(BuildParam buildParam)
        {
            if(buildParam.Result == BuildResult.Fail) return;
            switch (buildParam.CatalogUpdateType)
            {
                case ECatalogUpdateType.Local:
                    _CatalogLocal(buildParam.NewCatalogUrl, buildParam.CacheCatalogPath);
                    break;
                case ECatalogUpdateType.Update:
                    _CatalogUpdate(buildParam.NewCatalogUrl, buildParam.CacheCatalogPath, buildParam.CatalogReplaceOldUrl,  buildParam.CatalogReplaceNewUrl);
                    break;
                case ECatalogUpdateType.Remote:
                    _CatalogRemote(buildParam.NewCatalogUrl, buildParam.CacheCatalogPath, buildParam.CatalogReplaceOldUrl,  buildParam.CatalogReplaceNewUrl);
                    break;
            }
        }

        private static void _CatalogLocal(string newCatalogUrl, string cacheCatalogUrl)
        {
            if(!System.IO.Directory.Exists(cacheCatalogUrl))
                System.IO.Directory.CreateDirectory(cacheCatalogUrl);
            System.IO.File.Copy(newCatalogUrl, System.IO.Path.Combine(cacheCatalogUrl, $"catalog_{UnityEditor.PlayerSettings.bundleVersion}_Local_{System.DateTime.Now:yyyy-MM-dd-HH-mm-ss}.json"), true);
            UnityEditor.AssetDatabase.SaveAssets();
            UnityEditor.AssetDatabase.Refresh();
        }
        
        private static string FindNearestCatalogUrl()
        {
            var files = System.IO.Directory.GetFiles("Assets/HybridCLRGenerate/CacheCatalog", "*.json");
            System.DateTime nearest = System.DateTime.Now.AddYears(-100);
            string nearestFileUrl = "";
            string start = $"catalog_{UnityEditor.PlayerSettings.bundleVersion}";
            foreach (var e in files)
            {
                var fileName = System.IO.Path.GetFileNameWithoutExtension(e);
                if (fileName.StartsWith(start))
                {
                    string[] splitAry = fileName.Split('_');
                    string dateStr = splitAry[3];
                    System.DateTime thisDate = System.DateTime.ParseExact(dateStr, "yyyy-MM-dd-HH-mm-ss", null);
                    if (thisDate > nearest)
                    {
                        nearest = thisDate;
                        nearestFileUrl = e;
                    }
                }
            }

            return nearestFileUrl;
        }

        private static void _CatalogUpdate(string newCatalogUrl, string cacheCatalogUrl,
            string oldUrl = "{UnityEngine.AddressableAssets.Addressables.RuntimePath}",
            string newUrl = "http://localhost:80/")
        {
            string oldCatalogUrl = FindNearestCatalogUrl();
            _CatalogUpdate(oldCatalogUrl, newCatalogUrl, cacheCatalogUrl, oldUrl, newUrl);
        }

        private static void _CatalogUpdate(string oldCatalogUrl, string newCatalogUrl, string cacheCatalogUrl, string oldUrl = "{UnityEngine.AddressableAssets.Addressables.RuntimePath}", string newUrl = "http://localhost:80/")
        {
            string oldCatalog = System.IO.File.Exists(oldCatalogUrl) ? System.IO.File.ReadAllText(oldCatalogUrl) : "{}";
            string newCatalog = System.IO.File.ReadAllText(newCatalogUrl);
            string resultCatalog = newCatalog;
            var oldData = UnityEngine.JsonUtility.FromJson<Data>(oldCatalog);
            var newData = UnityEngine.JsonUtility.FromJson<Data>(newCatalog);
            for (int i = 0; i < newData.m_InternalIds.Count; i++)
            {
                string thisPath = newData.m_InternalIds[i];
                if (thisPath.EndsWith("bundle") && !oldData.m_InternalIds.Contains(thisPath) && thisPath.Contains(oldUrl))
                {
                    string newPath = thisPath.Replace(oldUrl, newUrl).Replace("\\", "/");
                    string thisPath2 = thisPath.Replace("\\", "\\\\");
                    resultCatalog = resultCatalog.Replace(thisPath2, newPath);
                }
            }
            if(!System.IO.Directory.Exists(cacheCatalogUrl))
                System.IO.Directory.CreateDirectory(cacheCatalogUrl);
            System.IO.File.WriteAllText(System.IO.Path.Combine(cacheCatalogUrl, $"catalog_{UnityEditor.PlayerSettings.bundleVersion}_update_{System.DateTime.Now:yyyy-MM-dd-HH-mm-ss}.json"),  resultCatalog);
            System.IO.File.WriteAllText(newCatalogUrl, resultCatalog);
            UnityEditor.AssetDatabase.SaveAssets();
            UnityEditor.AssetDatabase.Refresh();
        }
        
        private static void _CatalogRemote(string newCatalogUrl, string cacheCatalogUrl, string oldUrl = "{UnityEngine.AddressableAssets.Addressables.RuntimePath}", string newUrl = "http://localhost:80/")
        {
            string newCatalog = System.IO.File.ReadAllText(newCatalogUrl);
            string resultCatalog = newCatalog;
            var newData = UnityEngine.JsonUtility.FromJson<Data>(newCatalog);
            for (int i = 0; i < newData.m_InternalIds.Count; i++)
            {
                string thisPath = newData.m_InternalIds[i];
                if (thisPath.EndsWith("bundle"))
                {
                    string newPath = thisPath.Replace(oldUrl, newUrl);
                    resultCatalog = resultCatalog.Replace(thisPath, newPath);
                }
            }
            if(!System.IO.Directory.Exists(cacheCatalogUrl))
                System.IO.Directory.CreateDirectory(cacheCatalogUrl);
            System.IO.File.WriteAllText(System.IO.Path.Combine(cacheCatalogUrl, $"catalog_{UnityEditor.PlayerSettings.bundleVersion}_Remote_{System.DateTime.Now:yyyy-MM-dd-HH-mm-ss}.json"),  resultCatalog);
            System.IO.File.WriteAllText(newCatalogUrl, resultCatalog);
            UnityEditor.AssetDatabase.SaveAssets();
            UnityEditor.AssetDatabase.Refresh();
        }
        
        [System.Serializable]
        private class Data
        {
            public System.Collections.Generic.List<string> m_InternalIds = new System.Collections.Generic.List<string>();
        }
    }

    public enum ECatalogUpdateType
    {
        Local,
        Update,
        Remote
    }
}